package com.joyoung.common.utils;

import android.os.Environment;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Base64;


import com.joyoung.common.L;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 文件工具类(整理之后)
 *
 */
@SuppressWarnings({"all"})
public final class FileUtil {

    public static final String TAG = FileUtil.class.getSimpleName();

    private static final int MAX_BUFFER_LEN = 4 * 1024 * 1024; //最大4M

    private FileUtil() {}

    /** 判断是否有SD卡 */
    public static boolean isSDCardExist() {
        return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
    }

    public static String getExternalStorageDirectory(String fileName) {
        if (isSDCardExist()) {
            return Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + fileName;
        }
        return null;
    }

    /** 删除文件夹和文件 */
    public static void delete(File... files) {
        if (files == null || files.length <= 0) {
            return;
        }
        for (File file : files) {
            if (file.isFile()) {
                deleteFiles(file);
            } else {
                deleteDirectory(file, null);
            }
        }
    }

    /** 只删除文件 */
    public static void deleteFiles(File... files) {
        if (files == null || files.length <= 0) {
            return;
        }
        for (File file : files) {
            if (file == null || !file.exists() || file.isDirectory()) {
                continue;
            }
            boolean result = file.delete();
            if (!result) {
                L.e(TAG, "delete file:(" + file + ") fail");
            }
        }
    }

    /** 删除文件夹以及里面的所有满足的文件和文件夹 */
    public static void deleteDirectory(File dir, FileFilter filter) {
        if (dir == null || !dir.exists() || !dir.isDirectory()) {
            return;
        }
        File[] files = dir.listFiles(filter);
        for (File child : files) {
            if (child == null || !child.exists()) {
                continue;
            }
            if (child.isDirectory()) {
                deleteDirectory(child, filter);
            } else {
                if (filter == null || filter.accept(child)) {
                    deleteFiles(child);
                }
            }
        }
        boolean result = dir.delete();
        if (!result) {
            L.e(TAG, "delete dir:(" + dir + ") fail");
        }
    }

    public static void deleteDirectory(File dir, final long time) {
        if (dir == null || !dir.exists() || !dir.isDirectory()) {
            return;
        }
        FileFilter filter = new FileFilter() {
            @Override
            public boolean accept(File file) {
                return file.lastModified() < time;
            }
        };
        deleteDirectory(dir, filter);
    }

    private static void copyFile(File src, String root, String nameSuffix) {
        if (src == null) {
            return;
        }
        if (src.isDirectory()) {
            File file = new File(root, src.getName());
            if (!(file).exists()) {    //查看目录是否存在，不存在则新建
                boolean result = file.mkdirs();
                if (!result) {
                    L.e(TAG, "make dir fail:" + file);
                }
            }
            File[] children = src.listFiles();
            for (File child : children) {
                if (child == null) {
                    continue;
                }
                copyFile(child, root + File.separator + src.getName(), nameSuffix);
            }
        } else {
            FileInputStream in = null;
            FileOutputStream out = null;
            try {
                in = new FileInputStream(src);
                File targetFileRoot = new File(root);
                if (targetFileRoot.mkdirs()) {
                    L.i(TAG, targetFileRoot + " make dirs");
                }
                out = new FileOutputStream(root + File.separator + src.getName() + (nameSuffix == null ? "" : nameSuffix));
                int length;
                byte[] buffer = new byte[1024];
                while ((length = in.read(buffer)) != -1) {
                    out.write(buffer, 0, length);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                    if (out != null) {
                        out.close();
                    }
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    public static void copyFiles(String root, String nameSuffix, File... srcFiles) {
        if (srcFiles == null || srcFiles.length <= 0) {
            return;
        }
        for (File src : srcFiles) {
            copyFile(src, nameSuffix, root);
        }
    }

    /**
     * 拷贝文件
     *
     * @param root         拷贝的目标位置
     * @param nameSuffix   拷贝后文件的后缀
     * @param srcFileNames 需要拷贝的文件
     */
    public static void copyFiles(String root, String nameSuffix, String... srcFileNames) {
        if (srcFileNames == null || srcFileNames.length <= 0) {
            return;
        }
        for (String src : srcFileNames) {
            if (TextUtils.isEmpty(src)) {
                continue;
            }
            copyFile(new File(src), root, nameSuffix);
        }
    }

    public static boolean zip(String src, String root) {
        boolean result = false;
        File file = new File(src);
        ZipOutputStream zipOutStream = null;
        try {
            zipOutStream = new ZipOutputStream(new FileOutputStream(root));
            result = zipFile(file, File.separator, zipOutStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (zipOutStream != null) {
                try {
                    zipOutStream.finish();
                    zipOutStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            // 未压缩成功，删除压缩文件
            if (!result) {
                File tempFile = new File(root);
                deleteFiles(tempFile);
            }
        }
        return result;
    }

    private static boolean zipFile(File src, String root, @NonNull ZipOutputStream zipOutputSteam) {
        boolean result = false;
        if (src.isFile()) {
            FileInputStream inputStream = null;
            ZipEntry zipEntry = new ZipEntry(root + src.getName());
            try {
                inputStream = new FileInputStream(src);
                zipOutputSteam.putNextEntry(zipEntry);
                int len;
                byte[] buffer = new byte[4096];
                while ((len = inputStream.read(buffer)) != -1) {
                    zipOutputSteam.write(buffer, 0, len);
                }
                zipOutputSteam.closeEntry();
                result = true;
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        } else {
            String children[] = src.list();
            ZipEntry zipEntry = new ZipEntry(src.getName() + File.separator);
            if (children.length > 0) {
                for (String child : children) {
                    File childFile = new File(src, child);
                    result = zipFile(childFile, root + File.separator + src.getName() + File.separator, zipOutputSteam);
                    if (!result) {
                        return false;
                    }
                }
            } else {
                try {
                    zipOutputSteam.putNextEntry(zipEntry);
                    zipOutputSteam.closeEntry();
                    result = true;
                } catch (IOException e) {
                    result = false;
                    e.printStackTrace();
                }
            }
        }
        return result;
    }

    /**
     * 从文件读取文本
     *
     * @param fileName  文件名
     * @param maxLength 最大长度
     * @return 文本
     */
    public static String readString(String fileName, int maxLength) {
        String ret = null;
        FileInputStream byteOut = null;
        try {
            File f = new File(fileName);
            byteOut = new FileInputStream(f);
            int len = byteOut.available();
            if (maxLength > 0 && len > maxLength) {
                len = maxLength;
            }
            if (len > MAX_BUFFER_LEN) {
                len = MAX_BUFFER_LEN;
                L.d(TAG, "load file > MAX_LEN " + byteOut.available());
            }
            byte[] buffer = new byte[len];
            int readLength = byteOut.read(buffer);
            ret = new String(buffer, "utf-8");
            byteOut.close();
            L.d(TAG, "read file length= " + readLength);
        } catch (IOException e) {
            L.d(TAG, "load file failed. " + fileName);
        } finally {
            if (byteOut != null) {
                try {
                    byteOut.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return ret;
    }

    /** 从文件读取文本 */
    public static String readString(String fileName) {
        return readString(fileName, 0);
    }

    /**
     * 保存文本到文件
     *
     * @param fileName 文件名
     * @param text     文本
     * @param isWipe   是否擦除旧内容
     * @return 文件长度
     */
    public static int writeString(String fileName, String text, boolean isWipe) {
        int fileLength = 0;
        RandomAccessFile temp = null;
        try {
            File file = new File(fileName);
            file.getParentFile().mkdirs();
            if (!file.exists()) {
                if (!file.createNewFile()) {
                    L.d(TAG, "write file failed: " + fileName);
                    return 0;
                }
            }
            temp = new RandomAccessFile(file, "rw");
            if (isWipe) {
                temp.setLength(0);
            }
            temp.seek(temp.length());
            temp.write(text.getBytes("utf-8"));
            fileLength = (int) temp.length();
        } catch (IOException e) {
            L.d(TAG, "write file failed: " + fileName);
        } finally {
            if (temp != null) {
                try {
                    temp.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return fileLength;
    }

    public static String encodeBase64File(File file, int length) {
        String result = null;
        FileInputStream inputFile = null;
        byte[] buffer = new byte[length];
        try {
            inputFile = new FileInputStream(file);
            int readLength = inputFile.read(buffer);
            result = Base64.encodeToString(buffer, Base64.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputFile != null) {
                try {
                    inputFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }
}
